<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 原型继承

    // Person
    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.species = "human";
    }
    Person.prototype.skill = function () {
        console.log("think");
    }
    Person.prototype.say = function () {
        console.log(this.name, this.age);
    }

    // p的原型链：p -> Person.prototype -> Object.propotype -> null
    var p = new Person("张三", 18);
    console.log(p);
    p.say();

    // YellowPerson
    function YellowPerson(name, age, hobby) {
        this.hobby = hobby;
    }
    // 方法一：
    // 浅复制 (共用同一片内存空间 YellowPerson.propotype(Person.propotype) 
    // 优点：快速继承  
    // 缺点：YellowPerson.propotype新增的属性和方法也会影响 Person.propotype)

    // YellowPerson.prototype = Person.prototype; 


    // 方法二：
    // 通过拓宽原型链 达到继承的目的
    // 缺点：
    // 1.出现多余的属性(父类创建的实例的属性)
    // 2.



    // 优化  => 中间件继承
    function Fn() { };
    Fn.prototype = Person.prototype;
    var p = new Fn();  //创建一个纯净的对象 将该对象的原型 __proto__ 指向Person.prototype

    YellowPerson.prototype = p; // (将子类的原型对象 指向 父类创建的实例(引用该实例的原型链))
    // 此时yp的原型链：yp -> YellowPerson.prototype(p) -> Person.prototype -> Object.propotype -> null

    YellowPerson.prototype.skin = "yellow";
    YellowPerson.prototype.speak = function () {
        console.log("chinese");
    }

    // yp的原型链：yp -> YellowPerson.prototype -> Object.propotype -> null
    var yp = new YellowPerson("张三", 20, "跳舞");
    console.log(yp);
    yp.speak();
    yp.skill();

</script>

</html>